周回スコア計算

周回スコア表の計算プログラム

クランバトル第41回(2021/07)以降に対応しています。
第79回(2024/09)の調整まで実装。
プログラミング言語Pythonの仕様により、コピペした後にインデントを調整する必要があります。

 #!/usr/bin/env python3
 
 from fractions import Fraction
 from sys import argv
 
 # クランバトルの仕様。開催年*100+開催月
 version = 299912
 try:
     s = argv[1]
     if s != '-':
         version = int(s)
 except LookupError:
     pass
 # 出力する周回数の最大値
 loop_max = 50
 try:
     s = argv[2]
     if s != '-':
         loop_max = int(s)
 except LookupError:
     pass
 
 #
 # ここからデータ設定
 #
 
 # 古すぎる仕様ではロジックが流用できない
 assert version >= 202107
 
 # ボスのHPの単位, HP一覧表の各値にこの値が掛かる
 hp_unit = 1000000
 
 # 各ボスのHPの一覧
 boss_hp = []
 # 3段階目まで
 if False:
     pass
 elif version >= 202402:
     boss_hp.append( [ 9,12,15,18,23] )
     boss_hp.append( [12,15,20,23,30] )
     boss_hp.append( [35,40,45,50,58] )
 elif version >= 202304:
     boss_hp.append( [ 6, 8,10,12,15] )
     boss_hp.append( [ 8,10,13,15,20] )
     boss_hp.append( [20,22,25,28,30] )
 else:
     boss_hp.append( [ 6, 8,10,12,15] )
     boss_hp.append( [ 6, 8,10,12,15] )
     boss_hp.append( [12,14,17,19,22] )
 # 4段階目(全5段階の場合のみ)
 if False:
     pass
 elif version >= 202304:
     pass
 elif version >= 202204:
     boss_hp.append( [22,23,27,29,31] )
 else:
     boss_hp.append( [19,20,23,25,27] )
 # 最終段階
 if False:
     pass
 elif version >= 202409:
     boss_hp.append( [700,720,760,780,800] )
 elif version >= 202406:
     boss_hp.append( [600,620,660,680,700] )
 elif version >= 202402:
     boss_hp.append( [540,560,600,620,640] )
 elif version >= 202309:
     boss_hp.append( [270,280,300,310,320] )
 elif version >= 202304:
     boss_hp.append( [200,210,230,240,250] )
 elif version >= 202209:
     boss_hp.append( [145,150,175,195,210] )
 elif version >= 202206:
     boss_hp.append( [105,110,125,140,150] )
 elif version >= 202109:
     boss_hp.append( [ 95,100,110,120,130] )
 else:
     boss_hp.append( [ 85, 90, 95,100,110] )
 
 # 各ボスのスコア倍率の一覧
 # ボスHP*スコア倍率 が整数になるようにすること
 boss_mult = []
 boss_mult.append( [ Fraction(x,10) for x in [12,12,13,14,15] ] )
 boss_mult.append( [ Fraction(x,10) for x in [16,16,18,19,20] ] )
 if False:
     pass
 elif version >= 202304:
     boss_mult.append( [ Fraction(x,10) for x in [20,20,21,21,22] ] )
     boss_mult.append( [ Fraction(x,10) for x in [45,45,47,48,50] ] )
 else:
     boss_mult.append( [ Fraction(x,10) for x in [20,20,24,24,26] ] )
     boss_mult.append( [ Fraction(x,10) for x in [35,35,37,38,40] ] )
     boss_mult.append( [ Fraction(x,10) for x in [35,35,37,38,40] ] )
 
 # 次の段階に切り替わる周回数の境界
 # 途中の段階から開始する場合は、開始する段階まで0に設定する
 loop_sep = []
 if False:
     pass
 elif version >= 202309:
     loop_sep = [ 0, 6,22]
 elif version >= 202304:
     loop_sep = [ 3, 9,25]
 elif version >= 202112:
     loop_sep = [ 3,10,30,38]
 else:
     loop_sep = [ 3,10,30,40]
 
 #
 # データの要素数の整合性チェック
 #
 assert len(boss_hp) == len(boss_mult)
 for hp, mult in zip(boss_hp,boss_mult):
     assert len(hp) > 0
     assert len(hp) == len(mult)
 assert len(loop_sep) == len(boss_hp)-1
 for i in range(len(loop_sep)-1):
     assert loop_sep[i] >= 0
     assert loop_sep[i] <= loop_sep[i+1]
 
 #
 # ここから計算ロジック
 #
 
 stage_scores      = [] # 各段階の、全ボスを1体ずつ倒した場合の合計スコア
 stage_scores_diff = [] # 各段階の途中周回での、完了に必要な最大値と最小値の差
 for i in range(len(boss_hp)):
     scores = []
     for hp, mult in zip(boss_hp[i], boss_mult[i]):
         scores.append( round(hp_unit * hp * mult) )
     score = sum(scores)
     score_diff = score - min(scores)
     stage_scores.append(score)
     stage_scores_diff.append(score_diff)
 
 loop_scores = [] # 各周回の、周回完了に必要なスコアの最小値と最大値の対
 stage_loop_begin = [0] + loop_sep[:]
 stage_loop_end   = loop_sep[:] + [loop_max+1]
 score = 0
 for i in range(len(loop_sep)+1):
     loop_begin = stage_loop_begin[i]
     loop_end   = stage_loop_end[i]
     if loop_begin >= loop_end:
         continue
     for j in range(loop_end - loop_begin - 1):
         score += stage_scores[i]
         score_min = score
         score_max = score + stage_scores_diff[i]
         loop_scores.append( (score_min, score_max) )
     if i < len(loop_sep):
         score += stage_scores[i]
         loop_scores.append( (score, score) )
 
 #
 # ここから計算結果の出力
 #
 
 for iloop,v in enumerate(loop_scores,1):
     score_min, score_max = v
     if score_min == score_max:
         print( '|{:d}|>|CENTER:{:,d}|'.format(iloop, score_min) )
     else:
         print( '|{:d}|{:,d}|{:,d}|'.format(iloop, score_min, score_max) )

コメント

    スポンサー